package com.spsoft.core.listener;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * excel通用读取监听类
 *
 * @author : chenxudong
 * @date : 2023/12/5 15:21
 */
@Slf4j
public class ExcelListener<T> extends AnalysisEventListener<T> {
    /**
     * 自定义用于暂时存储data 可以通过实例获取该值
     */
    private final List<T> list = new ArrayList<>();

    /**
     * 这个每一条数据解析都会来调用
     */
    @Override
    public void invoke(T data, AnalysisContext context) {
        // 如果一行Excel数据均为空值，则不装载该行数据
        if (isLineNullValue(data)) {
            return;
        }
        log.info("解析到一条数据:{}", JSONObject.toJSONString(data));
        list.add(data);
    }

    /**
     * 所有数据解析完成了 都会来调用
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        String sheetName = context.readSheetHolder().getSheetName();
        log.info("sheet页：{}，所有数据解析完成，数据条数：{}", sheetName, list.size());
    }

    /**
     * 返回所有记录
     */
    public List<T> getRows() {
        return list;
    }

    /**
     * 判断整行单元格数据是否均为空
     */
    private boolean isLineNullValue(Object data) {
        if (data == null) {
            return true;
        }
        List<Field> fields = Arrays.stream(data.getClass().getDeclaredFields())
                .filter(f -> f.isAnnotationPresent(ExcelProperty.class))
                .collect(Collectors.toList());
        List<Boolean> lineNullList = new ArrayList<>(fields.size());
        for (Field key : fields){
            if (ReflectionKit.getFieldValue(data, key.getName()) == null) {
                lineNullList.add(Boolean.TRUE);
            } else {
                lineNullList.add(Boolean.FALSE);
            }
        }
        return lineNullList.stream().allMatch(Boolean.TRUE::equals);
    }
}
